<?php if (!defined('PmWiki')) exit();

/**	=== Attachtable FileInfo image extensions ===
 *	Copyright 2009 Eemeli Aro <eemeli@gmail.com>
 */

function FileInfoBMP( &$bmp, &$out ) {
	switch( $bmp['type_version'] ) {
		case 4:		$v = 'Windows 95/NT4'; break;
		case 5:		$v = 'Windows 98'; break;
		default:	$v = ( $bmp['type_os'] == 'Windows' ) ? 'Windows 3.x' : 'OS/2';
	}
	$out[] = "||$[Format]: ||$v ||";
	if (!empty( $bmp['header']['raw']['resolution_h'] )) {
		$x = sprintf( '%.1f', $bmp['header']['raw']['resolution_h'] * 0.0254 );
		$y = sprintf( '%.1f', $bmp['header']['raw']['resolution_v'] * 0.0254 );
		$out[] = "||$[Resolution]: ||$x &times; $y dpi ||";
	}
}

function FileInfoGIF( &$gif, &$out, $filepath, $cr ) {
	$out[] = "||$[Format]: ||GIF{$gif['version']} ||";
	$gif_file = file_get_contents($filepath);
	if ( $gif_file && preg_match_all( '/\x00\x21\xF9\x04.{4}\x00\x2C/s', $gif_file, $matches ) ) {
		$c = count($matches[0]);
		if ($c>1) {
			$out[] = "||$[Frames]: ||$c ||";
			$cr /= $c;
			$out['video.compression'] = '||$[Compresssion]: ||'.sprintf( '%.2f%%', 100*(1-$cr) ).' ||';
		}
	}
}

function FileInfoExifData( &$exif, &$out ) {
	foreach( array( '', 'Original', 'Digitized' ) as $st ) {
		$a = $st ? 'EXIF' : 'IFD0';
		if (!empty( $exif[$a]["DateTime$st"] )) {
			if (!empty( $exif['EXIF']["SubSecTime$st"] ))
				$exif[$a]["DateTime$st"] .= '.'.$exif['EXIF']["SubSecTime$st"];
			if ( ( $st != 'Digitized' ) || ( $exif[$a]['DateTimeDigitized'] != $exif[$a]['DateTimeOriginal'] ) )
				$out[] = "||$[DateTime$st]: ||{$exif[$a]["DateTime$st"]} ||";
		}
	}

	if (!empty( $exif['IFD0'] )) {
		$ifd =& $exif['IFD0'];
		if (!empty( $ifd['XResolution'] )) {
			$units = ( @$ifd['ResolutionUnit'] == 3 ) ? 'pixels/cm' : 'dpi';
			$x = explode( '/', $ifd['XResolution'] );
			if ( count($x) > 1 ) $x[0] /= $x[1];
			$y = explode( '/', $ifd['YResolution'] );
			if ( count($y) > 1 ) $y[0] /= $y[1];
			if ( $x && $y ) $out[] = "||$[Resolution]: ||{$x[0]} &times; {$y[0]} $units ||";
		}
		//$out[] = "|| ||";
		if (!empty( $ifd['Make'] )) {
			if (empty( $ifd['Model'] )) $cam = $ifd['Make'];
			else if (!strncasecmp( $ifd['Make'], $ifd['Model'], strlen($ifd['Make']) )) $cam = $ifd['Model'];
			else $cam = $ifd['Make'] . ' ' . $ifd['Model'];
			$out[] = "||$[Camera]: ||$cam ||";
		} else if (!empty( $ifd['Model'] )) $out[] = "||$[Camera]: ||{$ifd['Model']} ||";
		foreach( array( 'ImageDescription', 'Software', 'Artist', 'Copyright', 'UserComment' ) as $k )
			if (!empty( $ifd[$k] )) $out[] = "||$[$k]: ||{$ifd[$k]} ||";
	}
	if (!empty( $exif['COMPUTED']['ApertureFNumber'] ))
		$out[] = "||$[ApertureFNumber]: ||{$exif['COMPUTED']['ApertureFNumber']} ||";
	if (!empty( $exif['EXIF'] )) {
		$exif_longtext = array(
			'ExposureProgram' => array(
				1 => 'Manual',
				2 => 'Normal program',
				3 => 'Aperture priority',
				4 => 'Shutter priority',
				5 => 'Creative program',
				6 => 'Action program',
				7 => 'Portrait mode',
				8 => 'Landscape mode',
				-1 => 'Not defined'
			),
			'Flash' => array(
				0 => 'did not fire',
				1 => 'fired',
				5 => 'Strobe return light not detected',
				7 => 'Strobe return light detected',
				9 => 'fired, compulsory flash mode',
				13 => 'fired, compulsory flash mode, return light not detected',
				15 => 'fired, compulsory flash mode, return light detected',
				16 => 'did not fire, compulsory flash mode',
				24 => 'did not fire, auto mode',
				25 => 'fired, auto mode',
				29 => 'fired, auto mode, return light not detected',
				31 => 'fired, auto mode, return light detected',
				32 => 'No flash function',
				65 => 'fired, red-eye reduction mode',
				69 => 'fired, red-eye reduction mode, return light not detected',
				71 => 'fired, red-eye reduction mode, return light detected',
				73 => 'fired, compulsory flash mode, red-eye reduction mode',
				77 => 'fired, compulsory flash mode, red-eye reduction mode, return light not detected',
				79 => 'fired, compulsory flash mode, red-eye reduction mode, return light detected',
				89 => 'fired, auto mode, red-eye reduction mode',
				93 => 'fired, auto mode, return light not detected, red-eye reduction mode',
				95 => 'fired, auto mode, return light detected, red-eye reduction mode',
				-1 => 'unknown'
			),
			'LightSource' => array(
				0 => 'unknown',
				1 => 'Daylight',
				2 => 'Fluorescent',
				3 => 'Tungsten (incandescent light)',
				4 => 'Flash',
				9 => 'Fine weather',
				10 => 'Cloudy weather',
				12 => 'Daylight fluorescent (D 5700 – 7100K)',
				13 => 'Day white fluorescent (N 4600 – 5400K)',
				14 => 'Cool white fluorescent (W 3900 – 4500K)',
				15 => 'White fluorescent (WW 3200 – 3700K)',
				17 => 'Standard light A',
				18 => 'Standard light B',
				19 => 'Standard light C',
				20 => 'D55',
				21 => 'D65',
				22 => 'D75',
				23 => 'D50',
				24 => 'ISO studio tungsten',
				-1 => 'other light source'
			),
			'MeteringMode' => array(
				0 => 'unknown',
				1 => 'Average',
				2 => 'CenterWeightedAverage',
				3 => 'Spot',
				4 => 'MultiSpot',
				5 => 'Pattern',
				6 => 'Partial',
				-1 => 'other'
			),
			'ExposureMode' => array( 0 => 'Auto', 1 => 'Manual', 2 => 'Auto bracket' ),
			'WhiteBalance' => array( 0 => 'Auto', 1 => 'Manual' ),
			'ColorSpace' => array( 0 => 'Uncalibrated', 1 => 'sRGB' ),
			'ComponentsConfiguration' => array( "\x01\x02\x03\x00" => 'YCbCr', "\x04\x05\x06\x00" => 'RGB' )
		);

		$x =& $exif['EXIF'];
		foreach( array(
			'ExposureProgram', 'Flash', 'LightSource', 'MeteringMode', 'ExposureMode',
			'WhiteBalance', 'ColorSpace', 'ComponentsConfiguration',
			'ExposureTime', 'FNumber', 'SpectralSensitivity', 'ISOSpeedRatings', 'OECF',
			'ShutterSpeedValue', 'ApertureValue', 'BrightnessValue', 'ExposureBiasValue',
			'MaxApertureValue', 'FocalLength', 'FocalLengthIn35mmFilm', 'SubjectDistance',
			'DigitalZoomRatio', 'CompressedBitsPerPixel'
		) as $k )
			if (!empty( $x[$k] )) {
				if (!empty( $exif_longtext[$k] )) {
					$v = @$exif_longtext[$k][ $x[$k] ];
					if (!$v) $v = @$exif_longtext[$k][-1];
					if (!$v) $v = $x[$k];
				} else {
					$v = preg_match( '!^(\d+)/([1-9]\d*)$!', $x[$k], $m )
						? preg_replace( '/(?:\.|(\.\d*[1-9]))0+$/', '$1', sprintf( '%.6f', $m[1] / $m[2] ) )
						: $x[$k];
				}
				$out[] = "||$[$k]: ||$v ||";
			}
	}
}

function FileInfoPNG( &$png, &$out ) {
	global $TimeFmt;
	if (!empty( $png['tIME']['unix'] ))
		$out[] = '||$[Last modified]: ||'.strftime( $TimeFmt, $png['tIME']['unix'] ).' ||';

	if (!empty( $png['pHYs']['pixels_per_unit_x'] )) {
		$x = $png['pHYs']['pixels_per_unit_x'];
		$y = $png['pHYs']['pixels_per_unit_y'];
		if ( @$png['pHYs']['unit_specifier'] == 1 ) {
			$x = sprintf( '%.1f', $x*0.0254 );
			$y = sprintf( '%.1f', $y*0.0254 );
			$units = 'dpi';
		} else $units = ''; //@$png['pHYs']['unit'];
		$out[] = "||$[Resolution]: ||$x &times; $y $units ||";
	}

	if (!empty( $png['IHDR']['raw'] )) {
		$png_ihdr_raw_longtext = array(
			'color_type' => array( 0 => 'grayscale', 2 => 'RGB', 3 => 'palette', 4 => 'grayscale & alpha', 6 => 'RGBA' ),
			'filter_method' => array( 0 => 'adaptive' ),
			'interlace_method' => array( 0 => 'no interlace', 1 => 'Adam7' )
		);
		foreach( $png_ihdr_raw_longtext as $k => $a ) if (isset( $png['IHDR']['raw'][$k] )) {
			$v = @$a[ $png['IHDR']['raw'][$k] ];
			if (!$v) $v = 'unknown';
			$t = ucfirst(str_replace( '_', ' ', $k ));
			$out[] = "||$[$t]: ||$v ||";
		}
	}

	$png_longtext = array(
		'Compression method' => array( 'IHDR', 'compression_method_text' ),
		'Gamma' => array( 'gAMA', 'gamma' ),
		'sRGB rendering intent' => array( 'sRGB', 'rendering_intent_text' ),
		'ICC Profile name' => array( 'iCCP', 'profile_name' ),
		'Suggested palette name' => array( 'sPLT', 'palette_name' ),
		'Pixel calibration type' => array( 'pCAL', 'equation_type_text' ),
		'Pixel calibration name' => array( 'pCAL', 'calibration_name' ),
		'Image offset X' => array( 'oFFs', 'position_x' ),
		'Image offset Y' => array( 'oFFs', 'position_y' ),
		'Image offset units' => array( 'oFFs', 'unit' ),
		'Subject width' => array( 'sCAL', 'pixel_width' ),
		'Subject height' => array( 'sCAL', 'pixel_height' ),
		'Subject scale units' => array( 'sCAL', 'unit' ),
	);
	foreach ( $png_longtext as $t => $a ) if (isset( $png[ $a[0] ][ $a[1] ] ))
		$out[] = "||$[$t]: ||{$png[ $a[0] ][ $a[1] ]} ||";

	switch( @$png['IHDR']['raw']['color_type'] ) {
		case 2:		$png_colors = array( 'red', 'green', 'blue' ); break;
		case 3:		$png_colors = array( 'index' ); break;
		case 4:		$png_colors = array( 'gray', 'alpha' ); break;
		case 6:		$png_colors = array( 'red', 'green', 'blue', 'alpha' ); break;
		default:	$png_colors = array( 'gray' );
	}
	$png_colors_longtext = array(
		'Background color' => array( 'bKGD', 'background_' ),
		'Transparent color' => array( 'tRNS', 'transparent_' ),
		'Significant bits' => array( 'sBIT', 'significant_bits_' )
	);
	foreach ( $png_colors_longtext as $t => $a ) if (isset( $png[ $a[0] ][ $a[1].$png_colors[0] ] )) {
		$va = array();
		foreach ( $png_colors as $c ) {
			if (!isset( $png[ $a[0] ][ $a[1].$c ] )) break;
			$va[] = $png[ $a[0] ][ $a[1].$c ];
		}
		$out[] = "||$[$t]: ||".implode(', ',$va).' ||';
	}
	if (!empty($png['cHRM'])) {
		$va = array();
		foreach( array( 'white', 'red', 'green', 'blue' ) as $c ) {
			$x = @$png['cHRM']["{$c}_x"];
			$y = @$png['cHRM']["{$c}_y"];
			$va[] = "$c: $x, $y";
		}
		$out[] = "||$[Primary chromaticities]: ||".implode("\\\\\n",$va).' ||';
	}
}

function FileInfoTIFF( &$tiff, &$out ) {
	$pc = count($tiff['ifd']);
	if ($pc>1) $out[] = "||$[Page count]: ||$pc ||";
	foreach( $tiff['ifd'] as $i => $ifd ) {
		if ( empty($x) && !empty( $ifd['tags']['XResolution'] )) {
			$x = $ifd['tags']['XResolution'];
			$y = $ifd['tags']['YResolution'];
			switch( @$ifd['tags']['ResolutionUnit'] ) {
				case 2: $units = 'dpi'; break;
				case 3: $units = 'px/cm'; break;
				default: $units = ''; //@$ifd['tags']['ResolutionUnit_text'];
			}
			$out[] = "||$[Resolution]: ||$x &times; $y $units ||";
		}
		if ( !empty( $ifd['tags']['SubfileType_text'] ) )
			$out[] = "||$[Page type]: ||".($pc>1?"$i: ":'')."{$ifd['tags']['SubfileType_text']} image ||";
		if ( !empty( $ifd['tags']['PhotometricInterpretation_text'] )) {
			$out[] = "||$[Color type]: ||".($pc>1?"$i: ":'')."{$ifd['tags']['PhotometricInterpretation_text']} ||";
		}
	}
}
